#include "gskgldriverprivate.h"
#include "gskdebugprivate.h"
+#include "gsktextureprivate.h"
#include <gdk/gdk.h>
#include <epoxy/gl.h>
GLuint min_filter;
GLuint mag_filter;
GArray *fbos;
+ GskTexture *user;
gboolean in_use : 1;
- gboolean reserved : 1;
} Texture;
typedef struct {
{
Texture *t = data;
- g_warn_if_fail (!t->reserved);
+ if (t->user)
+ gsk_texture_clear_render_data (t->user);
g_clear_pointer (&t->fbos, g_array_unref);
glDeleteTextures (1, &t->texture_id);
{
Texture *t = value_p;
- if (t->reserved)
+ if (t->user)
continue;
if (t->in_use)
return NULL;
}
-int
-gsk_gl_driver_create_texture (GskGLDriver *driver,
- gboolean reserve,
- int width,
- int height)
+static Texture *
+create_texture (GskGLDriver *driver,
+ int width,
+ int height)
{
guint texture_id;
Texture *t;
- g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
-
if (width >= driver->max_texture_size ||
height >= driver->max_texture_size)
{
}
t = find_texture_by_size (driver->textures, width, height);
- if (t != NULL && !t->in_use)
+ if (t != NULL && !t->in_use && t->user == NULL)
{
GSK_NOTE (OPENGL, g_print ("Reusing Texture(%d) for size %dx%d\n",
t->texture_id, t->width, t->height));
t->in_use = TRUE;
- t->reserved = reserve;
- return t->texture_id;
+ return t;
}
glGenTextures (1, &texture_id);
t->min_filter = GL_NEAREST;
t->mag_filter = GL_NEAREST;
t->in_use = TRUE;
- t->reserved = reserve;
g_hash_table_insert (driver->textures, GINT_TO_POINTER (texture_id), t);
- return t->texture_id;
+ return t;
}
-void
-gsk_gl_driver_release_texture (GskGLDriver *driver,
- int texture_id)
+static void
+gsk_gl_driver_release_texture (gpointer data)
+{
+ Texture *t = data;
+
+ t->user = NULL;
+}
+
+int
+gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver,
+ GskTexture *texture,
+ int min_filter,
+ int mag_filter)
{
Texture *t;
+ cairo_surface_t *surface;
+
+ g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
+ g_return_val_if_fail (GSK_IS_TEXTURE (texture), -1);
+
+ t = gsk_texture_get_render_data (texture, driver);
+
+ if (t)
+ {
+ if (t->min_filter == min_filter && t->mag_filter == mag_filter)
+ return t->texture_id;
+ }
- g_return_if_fail (GSK_IS_GL_DRIVER (driver));
-
- t = gsk_gl_driver_get_texture (driver, texture_id);
- g_return_if_fail (t != NULL);
- g_return_if_fail (t->reserved);
+ t = create_texture (driver, gsk_texture_get_width (texture), gsk_texture_get_height (texture));
+
+ if (gsk_texture_set_render_data (texture, driver, t, gsk_gl_driver_release_texture))
+ t->user = texture;
- t->reserved = FALSE;
+ surface = gsk_texture_download (texture);
+ gsk_gl_driver_bind_source_texture (driver, t->texture_id);
+ gsk_gl_driver_init_texture_with_surface (driver,
+ t->texture_id,
+ surface,
+ min_filter,
+ mag_filter);
+
+ return t->texture_id;
+}
+
+int
+gsk_gl_driver_create_texture (GskGLDriver *driver,
+ int width,
+ int height)
+{
+ Texture *t;
+
+ g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
+
+ t = create_texture (driver, width, height);
+
+ return t->texture_id;
}
static Vao *
#include <gdk/gdk.h>
#include <graphene.h>
+#include <gsk/gsktexture.h>
+
G_BEGIN_DECLS
#define GSK_TYPE_GL_DRIVER (gsk_gl_driver_get_type ())
void gsk_gl_driver_begin_frame (GskGLDriver *driver);
void gsk_gl_driver_end_frame (GskGLDriver *driver);
+int gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver,
+ GskTexture *texture,
+ int min_filter,
+ int mag_filter);
int gsk_gl_driver_create_texture (GskGLDriver *driver,
- gboolean reserved,
int width,
int height);
-void gsk_gl_driver_release_texture (GskGLDriver *driver,
- int texture_id);
int gsk_gl_driver_create_vao_for_quad (GskGLDriver *driver,
int position_id,
int uv_id,
if (self->texture_id == 0)
{
self->texture_id = gsk_gl_driver_create_texture (self->gl_driver,
- FALSE,
width * scale_factor,
height * scale_factor);
gsk_gl_driver_bind_source_texture (self->gl_driver, self->texture_id);
if (render_node_needs_render_target (node))
{
item.render_data.render_target_id =
- gsk_gl_driver_create_texture (self->gl_driver, FALSE, item.size.width, item.size.height);
+ gsk_gl_driver_create_texture (self->gl_driver, item.size.width, item.size.height);
gsk_gl_driver_init_texture_empty (self->gl_driver, item.render_data.render_target_id);
gsk_gl_driver_create_render_target (self->gl_driver, item.render_data.render_target_id, TRUE, TRUE);
if (gsk_render_node_has_texture (node))
{
GskTexture *texture = gsk_render_node_get_texture (node);
- cairo_surface_t *surface = gsk_texture_download (texture);
int gl_min_filter = GL_NEAREST, gl_mag_filter = GL_NEAREST;
get_gl_scaling_filters (node, &gl_min_filter, &gl_mag_filter);
- /* Upload the Cairo surface to a GL texture */
- item.render_data.texture_id = gsk_gl_driver_create_texture (self->gl_driver,
- FALSE,
- item.size.width,
- item.size.height);
- gsk_gl_driver_bind_source_texture (self->gl_driver, item.render_data.texture_id);
- gsk_gl_driver_init_texture_with_surface (self->gl_driver,
- item.render_data.texture_id,
- surface,
- gl_min_filter,
- gl_mag_filter);
+ item.render_data.texture_id = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
+ texture,
+ gl_min_filter,
+ gl_mag_filter);
}
else if (gsk_render_node_has_surface (node))
{
/* Upload the Cairo surface to a GL texture */
item.render_data.texture_id = gsk_gl_driver_create_texture (self->gl_driver,
- FALSE,
item.size.width,
item.size.height);
gsk_gl_driver_bind_source_texture (self->gl_driver, item.render_data.texture_id);
#include "gsktextureprivate.h"
#include "gskdebugprivate.h"
+#include "gskrenderer.h"
/**
* GskTexture: (ref-func gsk_texture_ref) (unref-func gsk_texture_unref)
static void
gsk_texture_finalize (GskTexture *self)
{
+ gsk_texture_clear_render_data (self);
+
self->klass->finalize (self);
g_free (self);
return texture->klass->download (texture);
}
+gboolean
+gsk_texture_set_render_data (GskTexture *self,
+ gpointer key,
+ gpointer data,
+ GDestroyNotify notify)
+{
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ if (self->render_key != NULL)
+ return FALSE;
+
+ self->render_key = key;
+ self->render_data = data;
+ self->render_notify = notify;
+
+ return TRUE;
+}
+
+void
+gsk_texture_clear_render_data (GskTexture *self)
+{
+ if (self->render_notify)
+ self->render_notify (self->render_data);
+
+ self->render_key = NULL;
+ self->render_data = NULL;
+ self->render_notify = NULL;
+}
+
+gpointer
+gsk_texture_get_render_data (GskTexture *self,
+ gpointer key)
+{
+ if (self->render_key != key)
+ return NULL;
+
+ return self->render_data;
+}
int width;
int height;
+
+ gpointer render_key;
+ gpointer render_data;
+ GDestroyNotify render_notify;
};
struct _GskTextureClass {
GskTexture * gsk_texture_new_for_surface (cairo_surface_t *surface);
cairo_surface_t * gsk_texture_download (GskTexture *texture);
+gboolean gsk_texture_set_render_data (GskTexture *self,
+ gpointer key,
+ gpointer data,
+ GDestroyNotify notify);
+void gsk_texture_clear_render_data (GskTexture *self);
+gpointer gsk_texture_get_render_data (GskTexture *self,
+ gpointer key);
+
G_END_DECLS
#endif /* __GSK_TEXTURE_PRIVATE_H__ */